package ioc;

import java.beans.Introspector;  
import java.beans.PropertyDescriptor;  
import java.lang.reflect.Method;  
import java.net.URL;  
import java.util.ArrayList;  
import java.util.HashMap;  
import java.util.List;  
import java.util.Map;  
import org.dom4j.Document;  
import org.dom4j.Element;  
import org.dom4j.io.SAXReader;  

public class MyClassPathXmlApplicationContext {
	// xml所有的属性
	private ArrayList<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>();
	// xml中所有的bean
	private Map<String, Object> sigletons = new HashMap<String, Object>();

	public MyClassPathXmlApplicationContext(String file) {
		readXml(file);
		instanceBeans();
		instanceObject();
	}

	/**
	 * 注入
	 */
	private void instanceObject() {
		for (BeanDefinition beanDefinition : beanDefinitions) {
			// 判断有没有注入属性
			if (beanDefinition.getProperty() != null) {
				Object bean = sigletons.get(beanDefinition.getId());
				if (bean != null) {
					try {
						// 得到被注入bean的所有的属性
						PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors();
						// 得到所有的注入bean属性
						for (PropertyDefinition propertyDefinition : beanDefinition.getProperty()) {
							for (PropertyDescriptor propertyDescriptor : ps) {
								if (propertyDescriptor.getName().equals(propertyDefinition.getName())) {
									Method setter = propertyDescriptor.getWriteMethod();// 获取set方法
									if (setter != null) {
										setter.setAccessible(true);// 得到private权限
										// 注入属性
										setter.invoke(bean, sigletons.get(propertyDefinition.getRef()));
									}
									break;
								}
							}
						}
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * 实例所有的bean
	 */
	private void instanceBeans() {
		for (int i = 0; i < beanDefinitions.size(); i++) {
			BeanDefinition bd = beanDefinitions.get(i);
			try {
				try {
					if (bd.getClassName() != null && !bd.getClassName().equals(""))
						sigletons.put(bd.getId(), Class.forName(bd.getClassName()).newInstance());
				} catch (InstantiationException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	/**
	 * 读xml
	 * 
	 * @param file
	 */
	private void readXml(String file) {
		try {
			SAXReader reader = new SAXReader(); // 使用SAX方式解析XML
			URL xmlPath = this.getClass().getClassLoader().getResource(file);
			Document doc = reader.read(xmlPath);
			Element root = doc.getRootElement(); // 取得根节点
			List<Element> beans = root.elements();
			for (Element element : beans) {
				String id = element.attributeValue("id");// id;
				String clazz = element.attributeValue("class");
				BeanDefinition bd = new BeanDefinition(id, clazz);
				// 读取子元素
				if (element.hasContent()) {
					List<Element> propertys = element.elements();
					for (Element property : propertys) {
						String name = property.attributeValue("name");
						String ref = property.attributeValue("ref");
						PropertyDefinition pd = new PropertyDefinition(name, ref);
						bd.getProperty().add(pd);
					}
				}
				beanDefinitions.add(bd);
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	/**
	 * 通过名字得到bean
	 * 
	 * @param str
	 * @return
	 */
	public Object getBean(String str) {
		return sigletons.get(str);
	}
}
